import java.io.File;
import java.io.FileNotFoundException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Scanner;
import url.CleverURL;
import util.CleverBrowser;

/**
 *
 *
 * Last Modified: Oct 31, 2010<br>
 * Version: 1.0<br>
 * Created: Oct 31, 2010<br>
 * Author: Katie Kuksenok (katie.kuksenok@gmail.com)
 *
 * @author Katie
 */
public class IntervalSetter implements Runnable {

    public static final long MINUTE = 60000;
    public static final long HOUR = MINUTE * 60;
    public static final long HALF_DAY = HOUR * 12;
    public static final long DAY = HALF_DAY * 2;
    long[] updates;
    long max_samples;
    CleverBrowser cb;
    long interval;
    int methodID;
    int excess;
    ArrayList<CleverURL> seeds;

    public IntervalSetter(int methodID, long max_samples, long interval, CleverBrowser cb, int excess) {
        this.cb = cb;
        this.max_samples=max_samples;
        this.methodID = methodID;
        init(interval, excess);
    }

    public IntervalSetter(String methodName, long max_samples, long interval, CleverBrowser cb, int excess) {
        this.cb = cb;
        this.max_samples=max_samples;
        this.methodID = cb.getMethodID(methodName);
        init(interval, excess);
    }

    private void init(long interval, int excess) {
        this.interval = interval;
        ArrayList<String> seedList = cb.getSeeds(methodID);
        seeds = new ArrayList<CleverURL>();
        for (String url : seedList) {
            try {
                seeds.add(new CleverURL(url, cb, interval, methodID, false));
            } catch (MalformedURLException ex) {
                System.out.println("Could not make a CleverURL instance of " + url + "!");
            }
        }
        updates = new long[seeds.size()];
        if (excess < 0) {
            this.excess = 0;
        } else {
            this.excess = excess;
        }
        if(seeds.size()==0){
            System.out.println("This method is not associated with any seeds!");
            System.exit(1);
        }
    }

    public boolean stop() {
        for (int i = 0; i < updates.length; i++) {
            if (updates[i] >= max_samples) {
                return true;
            }
        }
        return false;
    }

    public int update() {
        if (seeds == null) {
            return -1;
        }
        int out = 0;
        for (int i = 0; i < seeds.size(); i++) {
            CleverURL cu = seeds.get(i);
            if (cu.update()) {
                System.out.print("1|");
                updates[i]++;
                out++;
            } else if (cu.isLostCause()) {
                System.out.print("x|");
            } else {
                System.out.print("0|");
            }
        }
        return out;
    }

    public static void main(String args[]) {
	
		System.out.println("CLASSPATH: "+System.getProperty("java.class.path"));
		
        long samples;
        try {
            samples = Long.parseLong(args[5]);
        } catch (Exception e) {
            samples = -1;
        }
        long interval;
        try {
            interval = Long.parseLong(args[6]) * 1000;
        } catch (Exception e) {
            interval = -1;
        }
        int excess;
        try {
            excess = Integer.parseInt(args[7]);
        } catch (Exception e) {
            excess = -1;
        }

        if (args.length < 8 || interval < 0 || excess < 0) {
            System.out.println("Arguments: MYSQLHOST MYSQLSCHEMA MYSQLUSER MYSQLPASS METHODNAME N_SAMPLES INTERVAL EXCESS [SEEDFILE]");
            System.out.println("  METHODNAME The name of the method with which this run in associated");
            System.out.println("  N_SAMPLES (long) the max. number of samples the most-sampled (see README) site gets");
            System.out.println("  INTERVAL (long) in seconds, the amount of time between desired updates");
            System.out.println("  EXCESS (int) is a measure of excess in sampling:");
            System.out.println("         if = 0, then there is no pause");
            System.out.println("         if > 1 - the pause is INTERVAL/EXCESS");
            System.out.println("  SEEDFILE (optional) The location of the file containing seed URLs in newlines");
            System.out.println("\n\nThe OUTPUT of this program is a file that describes what happened, at what time intervals, and so forth. "
                    + "All values are separated by \"|\", and can be pasted into a spreadsheet. Then, the \"text to column\" functionality can be used to "
                    + "make the data nice. Alternatively, one could search for the \"|\"s and replace them with commas, save it as a .csv, and receive much "
                    + "the same result.");
            System.exit(1);
        }
        CleverBrowser cb = new CleverBrowser(args[0], args[1], args[2], args[3], false);
        int methodID = cb.getMethodID(args[4]);
        if (args.length > 8) {
            try {
                ArrayList<String> seeds = new ArrayList<String>();
                Scanner s = new Scanner(new File(args[8]));
                while (s.hasNextLine()) {
                    seeds.add(s.nextLine());
                }
                System.out.println("Read in " + seeds.size() + " seeds from " + args[8]);
                cb.setSeeds(seeds, methodID);
            } catch (FileNotFoundException ex) {
                System.err.println("Could not read input file " + args[8]);
            }

        }
        IntervalSetter iu = new IntervalSetter(methodID, samples, interval, cb, excess);
        iu.run();

    }

    public void run() {
        System.out.println("Beginning interval update...");
        int sample = 0;
        System.out.println("Maximum samples: " + max_samples);
        System.out.println("Total valid seeds: " + seeds.size());
        for (int i = 0; i < seeds.size(); i++) {
            System.out.println("\tSeed " + (i + 1) + ": " + seeds.get(i).getAddress());
        }
        System.out.println("Desired Update Interval: " + interval + ", " + timeExplanation(interval));
        System.out.println("Sampling Excess: " + excess);
        System.out.println("Sampling Interval: " + (excess > 0 ? (interval / excess) + ", " + timeExplanation(interval / excess) : "no waiting"));
        System.out.print("SAMPLE|");
        for (int i = 0; i < seeds.size(); i++) {
            System.out.print("SEED " + (i + 1) + "|");
        }
        System.out.println("NUMBER OF SEEDS UPDATED|TIME SINCE LAST SAMPLE");
        while (true) {
            try {
                sample++;
                System.out.print(sample + "|");

                long current = System.currentTimeMillis();
                System.out.print(update());
                long diff = (System.currentTimeMillis() - current);

                System.out.print("|" + diff);
                if (diff > interval) {
                    System.out.print("|WARNING! This took longer than the desired interval.");
                }
                System.out.println();
                if (stop())
                    break;
                if (excess > 0 && (interval / excess - diff) > 0) {
                    Thread.sleep((interval / excess - diff));
                }

            } catch (InterruptedException ex) {
                System.out.println(ex);
            }
        }
    }

    public String timeExplanation(long interval) {
        if (MINUTE > interval) {
            return "less than a minute (" + MINUTE + ")";
        }
        if (HOUR > interval) {
            return "between a minute (" + MINUTE + ") and an hour (" + HOUR + ")";
        }
        if (HALF_DAY > interval) {
            return "between an hour (" + HOUR + ") and half a day (" + HALF_DAY + ")";
        }
        if (DAY > interval) {
            return "between half a day (" + HALF_DAY + ") and a day (" + DAY + ")";
        }
        return "longer than a day (" + DAY + ")";
    }
}
